﻿namespace ContentHolder
{
    internal readonly struct IntDictionary
    {
        public ushort[] Keys => this._keys;

        public int[] Values => this._values;

        private readonly ushort[] _keys;
        private readonly int[] _values;
        private readonly int _last;

        public IntDictionary(ushort[] keys, int[] values)
        {
            _keys = keys;
            _values = values;
            _last = keys.Length - 1;
        }

        public IntDictionary(Dictionary<ushort, int> dict)
        {
            var keys = dict.Select(q => q.Key).OrderBy(q => q).ToArray();
            var values = new int[keys.Length];
            for (int i = 0; i < keys.Length; i++)
            {
                values[i] = dict[keys[i]];
            }
            _keys = keys;
            _values = values;
            _last = keys.Length - 1;
        }

        public bool TryGetValue(ushort key, out int value)
        {
            value = 0;
            if (_last == -1)
            {
                return false;
            }

            if (_keys[0] == key)
            {
                value = _values[0];
                return true;
            }
            else if (_last == 0 || _keys[0] > key)
            {
                return false;
            }

            if (_keys[_last] == key)
            {
                value = _values[_last];
                return true;
            }
            else if (_keys[_last] < key)
            {
                return false;
            }

            var index = this.FindKeyIndex(key);
            if (index.HasValue)
            {
                value = index.Value;
                return true;
            }

            value = 0;
            return false;
        }

        private int? FindKeyIndex(ushort key)
        {
            var left = 1;
            var right = _last - 1;
            while (left <= right)
            {
                int mid = (left + right) >> 1;
                int d = _keys[mid] - key;

                if (d == 0)
                {
                    //value = _values[mid];
                    return mid;
                }
                else if (d > 0)
                {
                    right = mid - 1;
                }
                else
                {
                    left = mid + 1;
                }
            }

            return default(int?);
        }
    }
}
